using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;


/*
 * 添加事件 事件中心.获取实例.添加事件监听(string 事件名,UnityAction 委托);
 * 移除事件 事件中心.获取实例.移除事件监听(string 事件名,UNityAction 委托);
 * 
 * 事件触发 事件中心.获取实例.事件触发(string 事件名称);
 */

/// <summary>
/// 事件中心 单例模式对象 - 观察者设计模式
/// </summary>
public class 事件中心 : 单例_基础管理器<事件中心>
{
    //key 是事件的名称 
    //value 对应事件 的委托们
    private Dictionary<string, I事件属性> 事件容器 = new Dictionary<string, I事件属性>();

    private interface I事件属性{ }
    private class 事件类型<T> : I事件属性
    {
        public UnityAction<T> 事件;
        public 事件类型(UnityAction<T> 事件) => this.事件 += 事件;
    }

    private class 事件类型 : I事件属性
    {
        public UnityAction 事件;
        public 事件类型(UnityAction 事件) => this.事件 += 事件;
    }

    /// <summary>
    /// 返回所有已存在的事件名称
    /// </summary>
    /// <returns>返回已被订阅的事件名称数组</returns>
    public string[] 已存在的事件()
    {
        List<string> 返回 = new List<string>();
        foreach (string item in 事件容器.Keys)
            返回.Add(item);
        return 返回.ToArray();
    }

    /// <summary>
    /// 添加事件监听 方法
    /// </summary>
    /// <param name="事件名">事件的名字</param>
    /// <param name="委托">发生事件时调用的方法</param>
    public void 添加事件监听<T>(string 事件名, UnityAction<T> 委托)
    {
        if (事件容器.ContainsKey(事件名))
            (事件容器[事件名] as 事件类型<T>).事件 += 委托;
        else
            事件容器.Add(事件名, new 事件类型<T>(委托));
    }

    /// <summary>
    /// 添加事件监听 方法
    /// </summary>
    /// <param name="事件名">事件的名字</param>
    /// <param name="委托">发生事件时调用的方法</param>
    public void 添加事件监听(string 事件名, UnityAction 委托)
    {
        if (事件容器.ContainsKey(事件名))
            (事件容器[事件名] as 事件类型).事件 += 委托;
        else
            事件容器.Add(事件名, new 事件类型(委托));
    }


    /// <summary>
    /// 移除对应的事件监听
    /// </summary>
    /// <param name="事件名">事件的名称</param>
    /// <param name="委托">之前添加的委托</param>
    public void 移除事件监听<T>(string 事件名, UnityAction<T> 委托)
    {
        if (事件容器.ContainsKey(事件名))
            (事件容器[事件名] as 事件类型<T>).事件 -= 委托;
    }

    /// <summary>
    /// 移除对应的事件监听
    /// </summary>
    /// <param name="事件名">事件的名称</param>
    /// <param name="委托">之前添加的委托</param>
    public void 移除事件监听(string 事件名, UnityAction 委托)
    {
        if (事件容器.ContainsKey(事件名))
            (事件容器[事件名] as 事件类型).事件 -= 委托;
    }

    /// <summary>
    /// 触发事件
    /// </summary>
    /// <param name="事件名">需要触发的事件名称</param>
    public void 事件触发<T>(string 事件名, T 参数)
    {
        if (事件容器.ContainsKey(事件名))
            if((事件容器[事件名] as 事件类型<T>).事件!=null)
                (事件容器[事件名] as 事件类型<T>).事件(参数);
        else
            Debug.LogWarning("警告! 触发了没有人订阅的事件" + 事件名);
    }

    /// <summary>
    /// 不需要参数的触发事件
    /// </summary>
    /// <param name="事件名">需要触发的事件名称</param>
    public void 事件触发(string 事件名)
    {
        if (事件容器.ContainsKey(事件名))
            if ((事件容器[事件名] as 事件类型).事件 != null)
                (事件容器[事件名] as 事件类型).事件();
            else
                Debug.LogWarning("警告! 触发了没有人订阅的事件" + 事件名);
    }

    /// <summary>
    /// 主要用于场景切换时
    /// </summary>
    public void 清空事件中心()
    {
        事件容器.Clear();
    }

}
